package com.dss.code_generation.util;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;


/**
 * @Description:
 * @author: dongshoushan
 * @date: 2022年10月26日 10:58
 */
@Slf4j
public class IpUtil {
    private static List<String> blackPrefixs = Arrays.asList("docker0", "br-", "veth", "bridge", "virbr","eh1","TAP","Intel");
    public static String getLocalIp(){
        InetAddress address = findFirstNonLoopbackAddress();
        return address.getHostAddress();
    }
    public static InetAddress findFirstNonLoopbackAddress() {
        InetAddress result = null;
        try {
            int lowest = Integer.MAX_VALUE;
            for (Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces(); nics
                    .hasMoreElements();) {
                NetworkInterface ifc = nics.nextElement();
                if (ifc.isUp()) {
//                    log.info("Testing interface: " + ifc.getDisplayName());
                    if (ifc.getIndex() < lowest || result == null) {
                        lowest = ifc.getIndex();
                    }else if (result != null) {
                        continue;
                    }

                    // @formatter:off
                    if (!ignoreInterface(ifc.getDisplayName())) {
                        for (Enumeration<InetAddress> addrs = ifc.getInetAddresses(); addrs.hasMoreElements();) {
                            InetAddress address = addrs.nextElement();
//                            log.info("address interface: {},ip:{}", ifc.getDisplayName(),address.getHostAddress());
                            if (address instanceof Inet4Address
                                    && !address.isLoopbackAddress()
                                    && isPreferredAddress(address)) {
//                                log.info("Found non-loopback interface: {},ip:{}", ifc.getDisplayName(),address.getHostAddress());
                                result = address;
                            }
                        }
                    }
                    // @formatter:on
                }
            }
        }
        catch (IOException ex) {
            log.error("Cannot get first non-loopback address", ex);
        }

        if (result != null) {
            return result;
        }

        try {
            return InetAddress.getLocalHost();
        }
        catch (UnknownHostException e) {
            log.warn("Unable to retrieve localhost");
        }

        return null;
    }
    static boolean  ignoreInterface(String interfaceName) {
        for (String blackPrefix : blackPrefixs) {
            if (interfaceName.startsWith(blackPrefix)) {
                log.info("Ignoring interface: " + interfaceName);
                return true;
            }
        }
        return false;
    }
    static boolean isPreferredAddress(InetAddress address) {

//        if (this.properties.isUseOnlySiteLocalInterfaces()) {
//            final boolean siteLocalAddress = address.isSiteLocalAddress();
//            if (!siteLocalAddress) {
//                this.log.info("Ignoring address: " + address.getHostAddress());
//            }
//            return siteLocalAddress;
//        }
//        final List<String> preferredNetworks = this.properties.getPreferredNetworks();
//        if (preferredNetworks.isEmpty()) {
//            return true;
//        }
//        for (String regex : preferredNetworks) {
//            final String hostAddress = address.getHostAddress();
//            if (hostAddress.matches(regex) || hostAddress.startsWith(regex)) {
//                return true;
//            }
//        }
//        this.log.info("Ignoring address: " + address.getHostAddress());
        return true;
    }
}
